/**
 * PHOSIDE: PHosphorylation Site IDentification Engine.
 * Copyright 2009 Digital Biology Lab, University of Missouri.
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 3 of the License, or (at your option) any later
 * version. <p/> This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more
 * details.
 */

package phoside.ui;

import java.io.File;
import java.io.IOException;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;

import phoside.PhosideInit;
import phoside.PhosphoProteins;
import phoside.PhosphoProteinsImpl;

import phoside.disorder.DisorderInfoBatchWriter;
import phoside.disorder.DisorderInfoBatchWriterFasta;
import phoside.disorder.DisorderPredictorVSL2;
import phoside.disorder.DisorderUtil;

import phoside.io.ProteinsReader;
import phoside.io.fasta.PhosphoReaderFromFastaWithSitesInSequence;
import phoside.io.xml.PhosideXmlProteinsReader;
import phoside.io.xml.PhosideXmlProteinsWriter;
import phoside.io.xml.PhosphoProteinFieldValueFormatter;

import phoside.ui.task.DisorderPredictionTask;
import phoside.ui.task.ProteinsReadTask;
import phoside.ui.task.TaskUtil;

import phoside.util.FileExtensionsFilter;
import phoside.util.FilePathParser;
import phoside.util.StaticFinalValues;

/**
 *
 * @author gjj
 */
public class DisorderPredictionDialog extends javax.swing.JDialog {

    /** Creates new form PhosideTrainDialog */
    public DisorderPredictionDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        javax.swing.JPanel trainPanel = new javax.swing.JPanel();
        javax.swing.JPanel trainFilePanel = new javax.swing.JPanel();
        trainFileTextField = new javax.swing.JTextField();
        javax.swing.JButton trainFileButton = new javax.swing.JButton();
        javax.swing.JPanel inputfileoptionPanel = new javax.swing.JPanel();
        disorderPanel = new javax.swing.JPanel();
        saveDisordeFileTextField = new javax.swing.JTextField();
        saveDisorderFileButton = new javax.swing.JButton();
        javax.swing.JPanel OKPanel = new javax.swing.JPanel();
        OKBtn = new javax.swing.JButton();
        javax.swing.JButton cancelBtn = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        setTitle("Disorder prediction");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        trainPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Sequence file"));
        trainPanel.setMinimumSize(new java.awt.Dimension(400, 63));
        trainPanel.setPreferredSize(new java.awt.Dimension(500, 63));
        trainPanel.setLayout(new java.awt.GridBagLayout());

        trainFilePanel.setLayout(new java.awt.GridBagLayout());

        trainFileTextField.setToolTipText("Please select a FASTA training file");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        trainFilePanel.add(trainFileTextField, gridBagConstraints);

        trainFileButton.setText("Open");
        trainFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                trainFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        trainFilePanel.add(trainFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        trainPanel.add(trainFilePanel, gridBagConstraints);

        inputfileoptionPanel.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        trainPanel.add(inputfileoptionPanel, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(trainPanel, gridBagConstraints);

        disorderPanel.setBorder(javax.swing.BorderFactory.createTitledBorder("Save disorder result to"));
        disorderPanel.setLayout(new java.awt.GridBagLayout());

        saveDisordeFileTextField.setToolTipText("Please select file to save the model");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        disorderPanel.add(saveDisordeFileTextField, gridBagConstraints);

        saveDisorderFileButton.setText("Open");
        saveDisorderFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveDisorderFileButtonActionPerformed(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        disorderPanel.add(saveDisorderFileButton, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
        gridBagConstraints.weightx = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(disorderPanel, gridBagConstraints);

        OKBtn.setText("   OK   ");
        OKBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                OKBtnActionPerformed(evt);
            }
        });
        OKPanel.add(OKBtn);

        cancelBtn.setText("Cancel");
        cancelBtn.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelBtnActionPerformed(evt);
            }
        });
        OKPanel.add(cancelBtn);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
        gridBagConstraints.insets = new java.awt.Insets(5, 5, 5, 5);
        getContentPane().add(OKPanel, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void cancelBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelBtnActionPerformed
        setVisible(false);
        dispose();
}//GEN-LAST:event_cancelBtnActionPerformed

    private void OKBtnActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_OKBtnActionPerformed
        String dirPhospho = trainFileTextField.getText();
        if (dirPhospho.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify a file containing the protein sequences.");
            return;
        }
        
        String dirDisSaveTo = saveDisordeFileTextField.getText();
        if (dirDisSaveTo==null || dirDisSaveTo.length()==0) {
            JOptionPane.showMessageDialog(this, "Error: specify a file to save the disorder result.");
            return;
        }

        if (phoside.util.IOUtil.fileExist(dirDisSaveTo)) {
            int ret = JOptionPane.showConfirmDialog(this, "Are you sure to replace the existing disorder file?",
                    null, JOptionPane.YES_NO_OPTION);
            if (ret==JOptionPane.NO_OPTION) {
                return;
            }
        }

        //Reading phospho data
        String ext = FilePathParser.getExt(dirPhospho);

        PhosphoProteins phosphoData = new PhosphoProteinsImpl();
        ProteinsReader phosphoReader;
        if (ext.equalsIgnoreCase("xml")) {
            phosphoReader = new PhosideXmlProteinsReader(dirPhospho,
                    phosphoData, new PhosphoProteinFieldValueFormatter());
        } else {
            try {
               phosphoReader = new PhosphoReaderFromFastaWithSitesInSequence(dirPhospho,
                            phosphoData,StaticFinalValues.DEFAULTHEADERRULE);
            } catch (IOException e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(this, "Failed to read the fasta file");
                return;
            }
        }

        ProteinsReadTask phosphoReadTask = new ProteinsReadTask(phosphoReader);
        TaskUtil.execute(phosphoReadTask);
        if (!phosphoReadTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to read the file");
            return;
        }

        // predict disorder
        DisorderPredictorVSL2 disorderPredictor = new DisorderPredictorVSL2();
        DisorderPredictionTask disTask = new DisorderPredictionTask(phosphoData, disorderPredictor);
        TaskUtil.execute(disTask);
        if (!disTask.success()) {
            JOptionPane.showMessageDialog(this, "Failed to predict disorder");
            return;
        }

        Map<String,List<Double>>  mapDis = disTask.getDisorder();
        DisorderUtil.integrateDisorder(phosphoData, mapDis);

        // write disorder
        ext = FilePathParser.getExt(dirDisSaveTo);
        try {
            if (ext.equalsIgnoreCase("xml")) {
                PhosideXmlProteinsWriter writer = new PhosideXmlProteinsWriter(dirDisSaveTo,
                        new PhosphoProteinFieldValueFormatter());
                writer.write(phosphoData);
            } else {
                DisorderInfoBatchWriter writer = new DisorderInfoBatchWriterFasta(dirDisSaveTo);
                writer.write(mapDis);
            }
        } catch (IOException ex) {
            JOptionPane.showMessageDialog(this, "Failed to save the disorder information");
            ex.printStackTrace();
            return;
        }

        this.setVisible(false);
        this.dispose();
        JOptionPane.showMessageDialog(this, "Done.");
}//GEN-LAST:event_OKBtnActionPerformed

    private void trainFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_trainFileButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);
        
        ArrayList<String> exts = new ArrayList<String>(1);
        String fasta = "fasta";
        exts.add(fasta);
        fc.addChoosableFileFilter(new FileExtensionsFilter(exts,"Fasta file (.fasta)"));

        exts = new ArrayList<String>(1);
        String xml = "xml";
        exts.add(xml);
        fc.addChoosableFileFilter(new FileExtensionsFilter(exts,"Xml file (.xml)"));

        fc.setDialogTitle("Select a file...");
        int returnVal = fc.showOpenDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            trainFileTextField.setText(filePath);

            String fileName = FilePathParser.getName(filePath);
            String ext = FilePathParser.getExt(filePath);

            if (ext.equalsIgnoreCase("fasta")) {
                saveDisordeFileTextField.setText(PhosideInit.defaultPath+File.separator+fileName+"."+StaticFinalValues.DISORDERAPPENIX);
            } else if (ext.equalsIgnoreCase("xml")) {
                saveDisordeFileTextField.setText(PhosideInit.defaultPath+File.separator+fileName+"-with-disorder.xml");
            }
        }
    }//GEN-LAST:event_trainFileButtonActionPerformed

    private void saveDisorderFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveDisorderFileButtonActionPerformed
        JFileChooser fc = new JFileChooser(PhosideInit.defaultPath);

        ArrayList<String> exts = new ArrayList<String>(1);
        String fasta = "disorder";
        exts.add(fasta);
        fc.addChoosableFileFilter(new FileExtensionsFilter(exts,"Disorder file (.disorder)"));

        exts = new ArrayList<String>(1);
        String xml = "xml";
        exts.add(xml);
        fc.addChoosableFileFilter(new FileExtensionsFilter(exts,"Xml file (.xml)"));

        fc.setDialogTitle("Save the the disorder scores to...");
        int returnVal = fc.showSaveDialog(this);
        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            PhosideInit.defaultPath = file.getParent();

            String filePath = PhosideInit.defaultPath + File.separator + file.getName();
            saveDisordeFileTextField.setText(filePath);
        }
    }//GEN-LAST:event_saveDisorderFileButtonActionPerformed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton OKBtn;
    private javax.swing.JPanel disorderPanel;
    private javax.swing.JTextField saveDisordeFileTextField;
    private javax.swing.JButton saveDisorderFileButton;
    private javax.swing.JTextField trainFileTextField;
    // End of variables declaration//GEN-END:variables

}
